/*
 * $Id$
 * CONFIDENTIAL AND PROPRIETARY. (c) 2007 Revolution Health Group LLC. All rights reserved. 
 * This source code may not be disclosed to others, used or reproduced without the written permission of Revolution Health Group.
 *
 */
package org.javason.test;

import java.io.UnsupportedEncodingException;
import java.util.Locale;

import junit.framework.TestCase;

import net.sf.json.JSONArray;
import net.sf.json.JSONException;
import net.sf.json.JSONNull;
import net.sf.json.JSONObject;

import org.javason.jsonrpc.JsonRpcRequestFactory;
import org.javason.jsonrpc.JsonRpcServiceExporter;

import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.mock.web.MockHttpServletRequest;
import org.springframework.mock.web.MockHttpServletResponse;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.View;
import org.springframework.web.servlet.view.BeanNameViewResolver;

public abstract class AbstractJsonRpcTestCase extends TestCase {
	protected ApplicationContext _applicationContext = null;
	
	
	public AbstractJsonRpcTestCase() {
		super();
	}
	
	public AbstractJsonRpcTestCase(String name) {
		super(name);
	}
	
	
	abstract protected String[] getLocations();
	
	
	protected void setUp() {
   		try {
   			String locations[] = getLocations();
   			
   			if (locations != null && locations.length > 0) {
   				_applicationContext = new ClassPathXmlApplicationContext(locations);
   			}
   			
   		} catch (Exception exp) { exp.printStackTrace(); }
   	}
	
	public JSONObject callMethod(String serviceBeanName, String methodName, Object ... params) 
			throws Exception {
		
		return makeRequest(getServiceExporterForBean(serviceBeanName), 
				JsonRpcRequestFactory.createJsonRpcRequest(methodName, params));
	}

	
	public JSONObject makeRequest(String serviceBeanName, String methodName, JSONArray params) 
			throws Exception {
		    	
    	return makeRequest(getServiceExporterForBean(serviceBeanName), 
    			JsonRpcRequestFactory.createJsonRpcRequest(0, methodName, params));
	}
	
	public JSONObject makeRequest(String serviceBeanName, String methodName, JSONObject params) 
			throws Exception {
		
		assertNotNull(_applicationContext);
		JsonRpcServiceExporter serviceExporter = 
			(JsonRpcServiceExporter) _applicationContext.getBean(serviceBeanName);
				
		return makeRequest(serviceExporter, JsonRpcRequestFactory.createJsonRpcRequest(0, methodName, params));
	}
    	
   	protected JSONObject makeRequest(JsonRpcServiceExporter serviceExporter, 
   								  	 JSONObject jsonRpcRequest) throws Exception {
   		
   		assertNotNull(serviceExporter);
   		assertNotNull(jsonRpcRequest);
    	MockHttpServletRequest request = new MockHttpServletRequest("POST", "/");
    	MockHttpServletResponse response = new MockHttpServletResponse();
    	JSONObject jsonRsp = null;
		try {
			System.out.println("Sending request: " + request.toString());
			request.setContent(jsonRpcRequest.toString().getBytes("UTF-8"));

			ModelAndView mv = serviceExporter.handleRequest(request, response);
			renderModelAndView(mv, request, response);
			System.out.println(response.getContentAsString());
			
			jsonRsp = JSONObject.fromObject(response.getContentAsString());
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
			throw e;
		} catch (Exception e) {
			e.printStackTrace();
			throw e;
		}
		
		return jsonRsp;
    }
	
	protected void renderModelAndView(ModelAndView mv, 
									  MockHttpServletRequest request, 
									  MockHttpServletResponse response) throws Exception {
		
		BeanNameViewResolver viewResolver = 
			(BeanNameViewResolver) _applicationContext.getBean("beanNameViewResolver");
		
		assertNotNull(viewResolver);
		View view = viewResolver.resolveViewName(mv.getViewName(), Locale.getDefault());
		assertNotNull(view);
		view.render(mv.getModel(), request, response);
	}
	
	protected JsonRpcServiceExporter getServiceExporterForBean(String serviceBeanName) {
		assertNotNull(_applicationContext);
    	JsonRpcServiceExporter serviceExporter = 
    		(JsonRpcServiceExporter) _applicationContext.getBean(serviceBeanName);
    	return serviceExporter;
	}
	
	protected void assertNoError(JSONObject response) {
		try {
			assertTrue(JSONNull.getInstance().equals(response.get("error")));
		} catch (JSONException e) {
			throw new RuntimeException(e);
		}
	}
}
